package com.momo.service.authority;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.momo.common.req.sysmain.RedisUser;
import com.momo.common.res.authority.AclDto;
import com.momo.common.res.authority.AclModuleLevelDto;
import com.momo.common.res.authority.LoginAuthReq;
import com.momo.common.util.LevelUtil;
import com.momo.mapper.dataobject.AclDO;
import com.momo.mapper.dataobject.AclModuleDO;
import com.momo.mapper.mapper.sysSetting.AuthorityMapper;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by Kagome on 2019/3/23.
 * 本部 权限
 */
@Service
public class AdminAuthorityService {

    @Autowired
    private AdminSysCoreService sysCoreService;
    @Autowired
    private AuthorityMapper authorityMapper;
    @Autowired
    private DynamicAclModule dynamicAclModule;

    //动态权限菜单(总部和第三方通用)
    public List<AclModuleLevelDto> dynamicMenuTree(LoginAuthReq loginAuthReq, RedisUser redisUser) {
        List<AclDO> userAclList = sysCoreService.getUserAclList(loginAuthReq, redisUser);
        List<AclDto> aclDtoList = Lists.newArrayList();
        for (AclDO acl : userAclList) {
            AclDto dto = AclDto.adapt(acl);
            dto.setHasAcl(true);
            dto.setChecked(true);
            aclDtoList.add(dto);
        }
        return aclListToTree(loginAuthReq, aclDtoList);
    }

    //为角色授权 权限 之前， 需要查看该角色拥有哪些权限点，以及当前登录用户可以操作哪些权限
    public List<AclModuleLevelDto> roleTree(LoginAuthReq loginAuthReq, RedisUser redisUser) {
        // 1、当前用户已分配的权限点
        List<AclDO> userAclList = sysCoreService.getUserHavingAclList(loginAuthReq, redisUser);
        // 2、当前角色分配的权限点
        List<AclDO> roleAclList = sysCoreService.getRoleAclList(loginAuthReq.getRoleId(), loginAuthReq.getAclPermissionType());
        // 3、当前系统所有权限点
        List<AclDto> aclDtoList = Lists.newArrayList();

        Set<Long> userAclIdSet = userAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());
        Set<Long> roleAclIdSet = roleAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());

        List<AclDO> allAclList = authorityMapper.getAllAcl(null, null);
        for (AclDO acl : allAclList) {
            AclDto dto = AclDto.adapt(acl);
            if (userAclIdSet.contains(acl.getId())) {
                dto.setHasAcl(true);
            }
            if (roleAclIdSet.contains(acl.getId())) {
                dto.setChecked(true);
            }
            aclDtoList.add(dto);
        }
        return aclListToTree(loginAuthReq, aclDtoList);
    }

    public List<AclModuleLevelDto> aclListToTree(LoginAuthReq loginAuthReq, List<AclDto> aclDtoList) {
        if (CollectionUtils.isEmpty(aclDtoList)) {
            return Lists.newArrayList();
        }
        List<AclModuleLevelDto> aclModuleLevelList = aclModuleTree(loginAuthReq,aclDtoList);

        Multimap<Long, AclDto> moduleIdAclMap = ArrayListMultimap.create();
        for (AclDto acl : aclDtoList) {
            //临时启用状态 0启用  1禁用
            if ("0".equals(acl.getSysAclStatus())) {
                moduleIdAclMap.put(acl.getSysAclModuleId(), acl);
            }
        }
        bindAclsWithOrder(aclModuleLevelList, moduleIdAclMap);
        return aclModuleLevelList;
    }

    public void bindAclsWithOrder(List<AclModuleLevelDto> aclModuleLevelList, Multimap<Long, AclDto> moduleIdAclMap) {
        if (CollectionUtils.isEmpty(aclModuleLevelList)) {
            return;
        }
        for (AclModuleLevelDto dto : aclModuleLevelList) {
            List<AclDto> aclDtoList = (List<AclDto>) moduleIdAclMap.get(dto.getId());
            if (CollectionUtils.isNotEmpty(aclDtoList)) {
                Collections.sort(aclDtoList, aclSeqComparator);
                dto.setAclList(aclDtoList);
            }
            bindAclsWithOrder(dto.getAclModuleList(), moduleIdAclMap);
        }
    }

    public List<AclModuleLevelDto> aclModuleTree(LoginAuthReq loginAuthReq, List<AclDto> aclDtoList) {
        List<AclModuleDO> aclModuleList = authorityMapper.getAllAclModule(loginAuthReq.getAclPermissionType());
        List<AclModuleLevelDto> dtoList = Lists.newArrayList();
        Multimap<Long, AclModuleLevelDto> longLongMultimap = ArrayListMultimap.create();
        Set<AclModuleLevelDto> set = Sets.newHashSet();
        for (AclModuleDO aclModule : aclModuleList) {
            //状态 0启用  1禁用
            if ("0".equals(aclModule.getSysAcModulelStatus())) {
                AclModuleLevelDto aclModuleLevelDto = AclModuleLevelDto.adapt(aclModule);
                longLongMultimap.put(aclModuleLevelDto.getId(), aclModuleLevelDto);
                dtoList.add(aclModuleLevelDto);
            }
        }
        //为角色授予权限
        if (loginAuthReq.getAclPermissionType()==null){
            return aclModuleListToTree(dtoList);
        }
        //动态菜单 第三方账号为角色授权时，剔除没有的权限模块
        dynamicAclModule.ownAclModule(longLongMultimap, aclDtoList, set);
        List<AclModuleLevelDto> dtoListTwo = new ArrayList<>(set);
        return aclModuleListToTree(dtoListTwo);
    }

    public List<AclModuleLevelDto> aclModuleListToTree(List<AclModuleLevelDto> dtoList) {
        if (CollectionUtils.isEmpty(dtoList)) {
            return Lists.newArrayList();
        }
        // level -> [aclmodule1, aclmodule2, ...] Map<String, List<Object>>
        Multimap<String, AclModuleLevelDto> levelAclModuleMap = ArrayListMultimap.create();
        List<AclModuleLevelDto> rootList = Lists.newArrayList();

        for (AclModuleLevelDto dto : dtoList) {
            dto.setChecked(true);
            levelAclModuleMap.put(dto.getSysAclModuleLevel(), dto);
            if (LevelUtil.ROOT.equals(dto.getSysAclModuleLevel())) {
                rootList.add(dto);
            }
        }
        Collections.sort(rootList, aclModuleSeqComparator);
        transformAclModuleTree(rootList, LevelUtil.ROOT, levelAclModuleMap);
        return rootList;
    }

    public void transformAclModuleTree(List<AclModuleLevelDto> dtoList, String level, Multimap<String, AclModuleLevelDto> levelAclModuleMap) {
        for (int i = 0; i < dtoList.size(); i++) {
            AclModuleLevelDto dto = dtoList.get(i);
            String nextLevel = LevelUtil.calculateLevel(level, dto.getId());
            List<AclModuleLevelDto> tempList = (List<AclModuleLevelDto>) levelAclModuleMap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(tempList)) {
                Collections.sort(tempList, aclModuleSeqComparator);
                dto.setAclModuleList(tempList);
                transformAclModuleTree(tempList, nextLevel, levelAclModuleMap);
            }
        }
    }

    public Comparator<AclModuleLevelDto> aclModuleSeqComparator = new Comparator<AclModuleLevelDto>() {
        @Override
        public int compare(AclModuleLevelDto o1, AclModuleLevelDto o2) {
            return o1.getSysAclModuleSeq() - o2.getSysAclModuleSeq();
        }
    };
    public Comparator<AclDto> aclSeqComparator = new Comparator<AclDto>() {
        @Override
        public int compare(AclDto o1, AclDto o2) {
            return o1.getSysAclSeq() - o2.getSysAclSeq();
        }
    };
}
